package com.warrior.gatherclient.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.warrior.gatherclient.enums.ExecuteTypeEnum;
import com.warrior.gatherclient.grpc.GpcResponse;
import com.warrior.gatherclient.grpc.Messages;
import com.warrior.gatherclient.service.DispatchCenterService;
import com.warrior.gatherclient.service.GatherAdapterService;
import com.warrior.gathercommon.common.ResultCode;
import com.warrior.gathercommon.constants.CommonStatus;
import com.warrior.gathercommon.dto.GatherProDto;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import static java.util.concurrent.Executors.newScheduledThreadPool;

/**
 * @ClassName DispatchCenterServiceImpl.java
 * @Author xujian
 * @Description
 * @CreateTime 2020年12月11日 14:03:00
 */
@Service
@Slf4j
public class DispatchCenterServiceImpl implements DispatchCenterService, ApplicationContextAware {

    private ApplicationContext ctx;

    @Autowired
    private GrpcClientService grpcClientService;

    /**
     * @Description 适配器列表
     **/
    private Map<String, GatherAdapterService> beanMap = new HashMap<>();

    @Override
    public void start() {
        //获取运行配置
        Messages.Builder builder = Messages.newBuilder().setType(CommonStatus.CONSTANT_GRPC_SERVICE_RECEVE_CONFIG);
        GpcResponse gpcResponse = sendMessage(builder);
        String data = gpcResponse.getData();
        List<GatherProDto> propertys = JSONArray.parseArray(data, GatherProDto.class);
        if (!CollectionUtils.isEmpty(propertys)) {
            ScheduledExecutorService executor = newScheduledThreadPool(propertys.size());
            propertys.forEach(item -> {
                try {
                    GatherAdapterService adapter = getAdapter(item.getKey());
                    if (null == adapter) {
                        log.error("========== 没有获取到{}执行的接口,没法采集 ==========", item.getKey());
                    }
                    if (item.getType() == com.warrior.gatherclient.enums.ExecuteTypeEnum.ONE.getKey()) {
                        Messages.Builder messages = adapter.execute();
                        messages.setType(CommonStatus.CONSTANT_GRPC_SERVICE_SEND_MESSAGE);
                        sendMessage(messages);
                    } else if (item.getType() == ExecuteTypeEnum.DELAY.getKey()) {
                        executor.scheduleAtFixedRate(() -> {
                            Messages.Builder messages = adapter.execute();
                            messages.setType(CommonStatus.CONSTANT_GRPC_SERVICE_SEND_MESSAGE);
                            sendMessage(messages);
                        }, 0, item.getDelay(), TimeUnit.SECONDS);
                    }
                } catch (Exception e) {
                    log.info("============ 执行 {} 采集异常, errMsg:{} ==========", item.toString(), e.getMessage());
                }
            });
        }
    }

    private GpcResponse sendMessage(Messages.Builder messages) {
        try {
            GpcResponse gpcResponse = grpcClientService.sendMessage(messages);
            int status = gpcResponse.getStatus();
            String message = gpcResponse.getMessage();
            if (ResultCode.SUCCEED_CODE != status) {
                log.error("========== 调用采集服务异常 errorMsg: {} ===========", message);
            }
            return gpcResponse;
        } catch (Exception e) {
            log.error("========== grpc连接异常 msg:{} ============", e.getMessage());
        }
        return GpcResponse.getDefaultInstance();
    }

    protected GatherAdapterService getAdapter(String key) {
        if (!StringUtils.isEmpty(key)) {
            if (beanMap.isEmpty()) {
                initMap();
            }
            if (beanMap.containsKey(key)) {
                return beanMap.get(key);
            }
        }
        return null;
    }

    /**
     * 初始化适配器列表
     */
    private void initMap() {
        String[] beanNameArr = ctx.getBeanNamesForType(GatherAdapterService.class);
        for (int i = 0; i < beanNameArr.length; i++) {
            GatherAdapterService adapterService = (GatherAdapterService) ctx.getBean(beanNameArr[i]);
            beanMap.put(adapterService.getServiceKey(), adapterService);
        }
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.ctx = applicationContext;
    }

}
